Imports Microsoft.VisualBasic
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Diagnostics
Imports System.Linq
Imports System.Text
Imports System.Windows.Forms
Imports System.IO
Imports C4F.DevKit.Calendar.Parser

Namespace C4F.DevKit.Calendar.Components
	''' <summary>
	''' This component provides access to much of the calendaring functionality in a single component.
	''' </summary>
	<ToolboxItem(True), System.Drawing.ToolboxBitmap(GetType(CalendarService))> _
	Public Partial Class CalendarService
		Inherits Component
		#Region "Private Data"

		Private _calendarManager As CalendarManager = New CalendarManager()

		Private _calendarFilePath As String

		#End Region ' Private Data

		#Region "Private Properties"

		<Browsable(False)> _
		Private ReadOnly Property CalendarManager() As CalendarManager
			Get
				Return _calendarManager
			End Get
		End Property

		#End Region

		#Region "Constants"

		Private Const CALENDAR_FILE_EXTENSION As String = "ics"

		#End Region ' Constants

		#Region "Public Properties"

		''' <summary>
		''' The path to the file in which the current calendar is stored.
		''' </summary>
		Public Property CalendarFilePath() As String
			Get
				Return _calendarFilePath
			End Get
			Set(ByVal value As String)
				_calendarFilePath = value
			End Set
		End Property

		''' <summary>
		''' The path to the folder where Windows stores calendar files by default.
		''' </summary>
		Public ReadOnly Property WindowsCalendarFolderPath() As String
			Get
				If Not CalendarManager Is Nothing Then
					Return CalendarManager.WindowCalendarFolderPath
				Else
					Return String.Empty
				End If
			End Get
		End Property

		#End Region ' Public Properties

		#Region "Constructor"

		''' <summary>
		''' Creates a new Calendar Service component.
		''' </summary>
		Public Sub New()
			InitializeComponent()
		End Sub

		''' <summary>
		''' Creates a new Calendar Service component.
		''' </summary>
		''' <param name="container">The container to which to add this component.</param>
		Public Sub New(ByVal container As IContainer)
			container.Add(Me)
			InitializeComponent()
		End Sub

		#End Region ' Constructor

		#Region "Private Methods"

		Private Function GetSaveFilePath(ByVal pathToTry As String) As String
			Dim filePath As String = pathToTry

			If String.IsNullOrEmpty(filePath) Then
				filePath = CalendarFilePath
			End If

			If String.IsNullOrEmpty(filePath) Then
				filePath = PromptForSaveLocation()
			End If

			Return filePath
		End Function

		#End Region

		#Region "Public Methods"

		''' <summary>
		''' Displays a file dialog and prompts the user to enter a location to save
		''' a calendar file.
		''' </summary>
		''' <returns>The path file path selected by the user, or the empty string if they cancelled
		''' the dialog.</returns>
		Public Function PromptForSaveLocation() As String
			Dim filePath As String = String.Empty

			Using dlg As SaveFileDialog = New SaveFileDialog()
				dlg.AddExtension = True
				dlg.CheckPathExists = True
				dlg.Filter = String.Format("Calendar Files (*.{0})|*.{0}|All files (*.*)|*.*", CALENDAR_FILE_EXTENSION)

				If String.IsNullOrEmpty(Me.CalendarFilePath) AndAlso Directory.Exists(WindowsCalendarFolderPath) Then
					dlg.InitialDirectory = WindowsCalendarFolderPath
				End If

				If dlg.ShowDialog() = DialogResult.OK Then
					filePath = dlg.FileName
				Else
					filePath = String.Empty
				End If
			End Using

			Return filePath
		End Function

		''' <summary>
		''' Displays an open file dialog and prompts the user to select a
		''' calendar file to open.
		''' </summary>
		''' <returns>The path of the file to open, or the empty string if the
		''' user cancelled the dialog.</returns>
		Public Function PromptForOpenLocation() As String
			Dim filePath As String = String.Empty

			Using dlg As OpenFileDialog = New OpenFileDialog()
				dlg.AddExtension = True
				dlg.CheckPathExists = True
				dlg.Filter = String.Format("Calendar Files (*.{0})|*.{0}|All files (*.*)|*.*", CALENDAR_FILE_EXTENSION)
				dlg.Multiselect = False

				If String.IsNullOrEmpty(Me.CalendarFilePath) AndAlso Directory.Exists(WindowsCalendarFolderPath) Then
					dlg.InitialDirectory = WindowsCalendarFolderPath
				End If

				If dlg.ShowDialog() = DialogResult.OK Then
					filePath = dlg.FileName
				Else
					filePath = String.Empty
				End If
			End Using

			Return filePath
		End Function

		''' <summary>
		''' Retrieves all appointments from the current calendar (specified by
		''' CalendarFilePath), or a user-selected calendar if there is no
		''' current calendar.
		''' </summary>
		''' <returns>A collection of all the appointments from the calendar.</returns>
		Public Function GetAllAppointments() As IEnumerable(Of Appointment)
			If String.IsNullOrEmpty(CalendarFilePath) Then
				Return Me.GetAllAppointments(Nothing)
			Else
				Return Me.GetAllAppointments(CalendarFilePath)
			End If
		End Function

		''' <summary>
		''' Retrieves all appointments from the calendar specified.
		''' </summary>
		''' <param name="filePath">The path of the calendar file to get appointments from.
		''' If this is null, CalendarService will use CalendarFilePath, or prompt the user
		''' for a file if CalendarFilePath is null.</param>
		''' <returns>A collection of all the appointments from the calendar.</returns>
		Public Function GetAllAppointments(ByVal filePath As String) As IEnumerable(Of Appointment)
			If CalendarManager Is Nothing Then
				Throw New CalendarManagerIsNullException("CalendarManager property has not been set.")
			End If

			If String.IsNullOrEmpty(filePath) Then
				filePath = CalendarFilePath
			End If

			If String.IsNullOrEmpty(filePath) Then
				filePath = PromptForOpenLocation()
			End If

			Return CalendarManager.GetAllAppointments(filePath)
		End Function

		''' <summary>
		''' Creates a new calendar, prompting the user to select a place to save
		''' the file.
		''' </summary>
		Public Sub CreateCalendar()
			Dim calendarPath As String = PromptForSaveLocation()

			If String.IsNullOrEmpty(calendarPath) Then
				Return
			End If

			CalendarManager.CreateCalendar(calendarPath)
			CalendarFilePath = calendarPath
		End Sub

		''' <summary>
		''' Adds the specified appointments to the specified calendar file.
		''' </summary>
		''' <param name="filePath">The file of the calendar to save the appointments to.
		''' If this is null, CalendarService will use CalendarFilePath, or failing that, will
		''' prompt the user for a location.</param>
		''' <param name="appts">The appointments to add.</param>
		Public Sub AddAppointments(ByVal filePath As String, ByVal appts As IEnumerable(Of Appointment))
			If CalendarManager Is Nothing Then
				Throw New CalendarManagerIsNullException("CalendarManager property has not been set.")
			End If

			filePath = GetSaveFilePath(filePath)

			If String.IsNullOrEmpty(filePath) Then
				Return
			End If

			CalendarManager.AddAppointments(filePath, appts)
		End Sub

		''' <summary>
		''' Adds the specified appointments to the current calendar, or if there is
		''' none, to the calendar specified by the user when they are prompted.
		''' </summary>
		''' <param name="appts">The appointments to add.</param>
		Public Sub AddAppointments(ByVal appts As IEnumerable(Of Appointment))
			AddAppointments(String.Empty, appts)
		End Sub

		''' <summary>
		''' Adds the specified appointments to the current calendar, or if there is
		''' none, to the calendar specified by the user when they are prompted.
		''' </summary>
		''' <param name="appt">The appointments to add.</param>
		Public Sub AddAppointment(ByVal appt As Appointment)
			If String.IsNullOrEmpty(CalendarFilePath) Then
				AddAppointment(Nothing, appt)
			Else
				AddAppointment(CalendarFilePath, appt)
			End If
		End Sub

		''' <summary>
		''' Adds the specified appointment to the specified calendar file.
		''' </summary>
		''' <param name="filePath">The file of the calendar to add the appointment to.
		''' If this is null, CalendarService will use CalendarFilePath, or failing that, will
		''' prompt the user for a location.</param>
		''' <param name="appt">The appointment to add.</param>
		Public Sub AddAppointment(ByVal filePath As String, ByVal appt As Appointment)
			If CalendarManager Is Nothing Then
				Throw New CalendarManagerIsNullException("CalendarManager property has not been set.")
			End If

			If String.IsNullOrEmpty(filePath) Then
				filePath = CalendarFilePath
			End If

			If String.IsNullOrEmpty(filePath) Then
				filePath = PromptForOpenLocation()
			End If

			If String.IsNullOrEmpty(filePath) Then
				Return
			End If

			CalendarManager.AddAppointment(filePath, appt)
		End Sub

		''' <summary>
		''' Updates the information in an existing appointment.
		''' </summary>
		''' <param name="appt">The new version of the appointment to put in the calendar. This appointment
		''' will replace the appointment in the Calendar with the same UID.</param>
		Public Sub EditAppointment(ByVal appt As Appointment)
			EditAppointment(CalendarFilePath, appt)
		End Sub

		''' <summary>
		''' Updates the information in an existing appointment.
		''' </summary>
		''' <param name="appt">The new version of the appointment to put in the calendar. This appointment
		''' will replace the appointment in the Calendar with the same UID.</param>
		''' <param name="filePath">The calendar file to be edited.</param>
		Public Sub EditAppointment(ByVal filePath As String, ByVal appt As Appointment)
			If CalendarManager Is Nothing Then
				Throw New CalendarManagerIsNullException("CalendarManager property has not been set.")
			End If

			filePath = GetSaveFilePath(filePath)

			If String.IsNullOrEmpty(filePath) Then
				Return
			End If

			CalendarManager.EditAppointment(filePath, appt)
		End Sub

		''' <summary>
		''' Prompts the user for a calendar file and imports the events from
		''' that calendar into the current calendar.
		''' </summary>
		Public Sub ImportCalendar()
			Dim calendarToImport As String = PromptForOpenLocation()

			If String.IsNullOrEmpty(calendarToImport) Then
				Return
			End If

			ImportCalendar(calendarToImport)
		End Sub

		''' <summary>
		''' Prompts the user for a location to which to save the current calendar,
		''' and exports the current calendar to a file in that location.
		''' </summary>
		Public Sub ExportCalendar()
			Dim exportTarget As String = PromptForSaveLocation()

			If String.IsNullOrEmpty(exportTarget) Then
				Return
			End If

			ExportCalendar(exportTarget)
		End Sub

		''' <summary>
		''' Imports appointments from a calendar into the current calendar.
		''' </summary>
		''' <param name="filePath">The path of the calendar file to import.</param>
		Public Sub ImportCalendar(ByVal filePath As String)
			CalendarManager.ImportCalendar(filePath, CalendarFilePath)
		End Sub

		''' <summary>
		''' Exports appointments from the current calendar to a file.
		''' </summary>
		''' <param name="filePath">The file to which to save the appointments.</param>
		Public Sub ExportCalendar(ByVal filePath As String)
			CalendarManager.ExportCalendar(filePath, CalendarFilePath)
		End Sub

		''' <summary>
		''' Imports an appointment into the current calendar, or the calendar
		''' selected by the user when prompted if there is not current calendar.
		''' </summary>
		''' <param name="appt">The appointment to import.</param>
		''' <param name="filePath">The file path of the calendar to import into.</param>
		Public Sub Import(ByVal appt As Appointment, ByVal filePath As String)
			CalendarManager.Import(filePath, appt)
		End Sub

		''' <summary>
		''' Exports an appointment to another calendar.
		''' </summary>
		''' <param name="appt">The appointment to export.</param>
		''' <param name="filePath">The path of the calendar file to export to.</param>
		Public Sub Export(ByVal appt As Appointment, ByVal filePath As String)
			CalendarManager.Export(filePath, appt)
		End Sub

		''' <summary>
		''' Gets all windows contacts associated with the user currently logged in.
		''' </summary>
		''' <returns>A list of Attendees converted from a C4F.DevKit.Contacts.SimpleContactView object.</returns>
		''' <remarks>Use the Contacts assembly shipped with the VS Express Developer Kit. </remarks>
		Public Function GetAllWindowsContactsAsAttendees() As List(Of Attendee)
			Return _calendarManager.GetAllWindowsContactsAsAttendees()
		End Function

		#End Region ' Public Methods
	End Class
End Namespace
